import "./../topic-sider-bar/sider-modal/DeviceNodeManagePopUp.scss";
import {
    ChangeEvent,
    forwardRef,
    useCallback,
    useContext,
    useEffect,
    useImperativeHandle,
    useMemo,
    useRef,
    useState,
} from "react";
import {
    Modal,
    Input,
    Space,
    Form,
    Select,
    Row,
    Col,
    Tabs,
    Upload,
    UploadProps,
    Button,
    Divider,
    Tree,
    Checkbox,
    Empty,
    Tooltip,
    Alert,
} from "antd";
import LoadingWapper from "../../../components/loading/LoadingWapper";
import systemApi from "../../../api/system";
import {
    DocConfig,
    DocInstance,
    TopicNodeActionType,
    TopicType,
} from "../../../utils/types";
import {
    addTreePropertyForList,
    arrayTreeFilter,
    commonErrorMsg,
    commonSuccessMsg,
    deepCloneV2,
    dfsRecursive,
    dfsRecursiveFromInner,
    expandedKeysFun,
    filterTree,
    findHalfCheckedKeys,
    generateTreeData,
    getChangeEventValue,
    getCheckBoxChangeEventValue,
    getNodeChildDeviceNodeCheckedCount,
    getNodeChildDeviceNodeCount,
    handleJumpEditPage,
    insertChildNodeListToTree,
    insertPeerNodeListToTree,
    insertTopPeerNodeListToTree,
    isEmpty,
    makeClassNameList,
    swapListElements,
    toastShort,
    tree2List,
} from "../../../utils";
import {
    ArrowLeftOutlined,
    ArrowRightOutlined,
    CheckOutlined,
    DownOutlined,
    ExclamationCircleOutlined,
    ExpandAltOutlined,
    LeftCircleOutlined,
    PartitionOutlined,
    PlusCircleOutlined,
    PlusCircleTwoTone,
    QuestionCircleOutlined,
    RedoOutlined,
    RightCircleOutlined,
    UndoOutlined,
    VerticalAlignMiddleOutlined,
} from "@ant-design/icons";
import {
    generateDocInstance,
    processDocInstanceBeforeUpdate,
} from "../word-editor/editor-doc-item-generate";
import { useLocation } from "react-router-dom";
import TopicTreeContextMenu from "../../../components/context-menu/TopicTreeContextMenu";
import comDocContext from "../../../context/DocContext";
import { throttle } from "lodash";
import { CheckboxChangeEvent } from "antd/es/checkbox";
import AddTopicMoal from "../topic-sider-bar/sider-modal/AddTopicMoal";
import ReNameTopicModal from "../topic-sider-bar/sider-modal/ReNameTopicModal";
import useStateDebounce from "../../../hooks/useStateDebounce";
import emitter from "../../../utils/emitter";

interface Props { }

const { Search } = Input;

type DeviceSortType = "checked" | "default_up" | "default_down"

const TopicManagePage = (props: Props) => {
    const {
        //规划数据实例
        comDocInstance,
        _setComDocInstance,
        //规划配置信息
        comDocConfig,
        currentFocusedDocItem,
        _setComFocusTopicNode,
    } = useContext(comDocContext);

    const contextMenuRef = useRef<any>(null);
    const pureTextTopicTreeRef = useRef<any>(null);
    const [windowFullHeight, setWindowFullHeight] = useState<number>(0);
    const [currentStep, setCurrentStep] = useState<
        "selectTitle" | "selecteDevice"
    >("selectTitle");
    //所有规划大纲
    const [topicList, setTopicList] = useState<TopicType[]>([]);

    const [draggingNodeKey, setDraggingNodeKey] = useState(null);

    const [pureTextTopicTreeHighLightNode, setPureTextTopicTreeHighLightNode] =
        useState<TopicType>(null);
    const [pureTextTopicTreeSelectedNode, setPureTextTopicTreeSelectedNode] =
        useState<TopicType>(null);

    const [pureTextTreeDataCheckedKeyList, setPureTextTreeDataCheckedKeyList] =
        useState<string[]>([]);
    //搜索
    const [
        pureTextTopicTreeDataSearchValue,
        setPureTextTopicTreeDataSearchValue,
    ] = useState("");
    const [pureTextTopicTreeExpandedKeys, setPureTextTopicTreeExpandedKeys] =
        useState<string[]>([]);

    const [deviceTopicSearchValue, setDeviceTopicSearchValue] =
        useState<string>("");

    const [deviceListSortType, setDeviceListSortType] =
        useState<DeviceSortType>("checked");

    const [topicListHistoryList, setTopicListHistoryList] = useState<{ _topicList: TopicType[], _pureTextTreeDataCheckedKeyList: string[] }[]>([]);
    const [topicListHistoryIndex, setTopicHistoryIndex] = useState(-1);

    const [delayUpdateComDocInstance, setDelayUpdateComDocInstance] =
        useState<DocInstance>(comDocInstance);

    const debouncedComDocInstance = useStateDebounce(
        delayUpdateComDocInstance,
        100
    );

    const [filteredForPureTopicTreeData, setFilteredForPureTopicTreeData] = useState<TopicType[]>([]);

    const [
        filteredForPureTopicTreeExpandedKeys,
        setFilteredForPureTopicTreeExpandedKeys,
    ] = useState<string[]>([]);

    /***** 纯展示 *****/
    const realTextTopicTreeRef = useRef<any>(null);

    const [
        realTextTopicTreeDataSearchValue,
        setRealTextTopicTreeDataSearchValue,
    ] = useState<string>("");

    const [realTextTopicTreeSelectedNode, setRealTextTopicTreeSelectedNode] =
        useState<TopicType>(null);

    const [realTextTopicTreeHighLightNode, setRealTextTopicTreeHighLightNode] =
        useState<TopicType>(null);

    const [realTextTopicTreeExpandedKeys, setRealTextTopicTreeExpandedKeys] =
        useState<string[]>([]);

    const [filteredForRealTopicTreeData, setFilteredForRealTopicTreeData] = useState<TopicType[]>([]);

    const [
        filteredForRealTopicTreeExpandedKeys,
        setFilteredForRealTopicTreeExpandedKeys,
    ] = useState<string[]>([]);

    const [currentDeviceType, setCurrentDeviceType] = useState<"current" | "all">(
        "current"
    );

    useEffect(() => {
        _setComDocInstance({ ...debouncedComDocInstance });
    }, [debouncedComDocInstance]);

    useEffect(() => {
        setWindowFullHeight(window.innerHeight);
    }, []);

    useEffect(() => {
        if (comDocInstance) {
            resetTopicHistoryList(comDocInstance.topicList);
            // resetTopicHistoryList(deepCloneV2(comDocInstance.topicList));
        }
    }, [comDocInstance]);

    const updateTopicList = (newTopicList: TopicType[]) => {
        setTopicList(deepCloneV2(newTopicList));
        let _topicListHistoryList = topicListHistoryList;
        _topicListHistoryList.push({
            _topicList: deepCloneV2(newTopicList),
            _pureTextTreeDataCheckedKeyList: deepCloneV2(pureTextTreeDataCheckedKeyList)
        });
        setTopicHistoryIndex(_topicListHistoryList.length - 1);
        setTopicListHistoryList([..._topicListHistoryList]);
    };

    const getInitPureTextTopicCheckedIdList = (initTopicList: TopicType[]) => {
        let result = [];
        let _tree: TopicType[] = generateTreeData(
            addTreePropertyForList(initTopicList)
        );
        dfsRecursive(_tree, (node: TopicType) => {
            if (node.topicType == "text") {
                if (node.checked) {
                    result.push(node.id);
                } else if (
                    node.children &&
                    node.children
                        .filter((ele) => ele.checked)
                        .filter((ele) => ele.topicType === "device").length
                ) {
                    result.push(node.id);
                }
            }
        });
        return result;
    };

    const topicTree = useMemo(() => {
        let _tree = generateTreeData(addTreePropertyForList(topicList));
        let serialNumberList = [];
        dfsRecursive(_tree, (topic: TopicType, level: number) => {
            if (topic.topicType == "text") {
                const childDeviceNodeCount = getNodeChildDeviceNodeCount(topic);
                const childDeviceNodeCheckedCount =
                    getNodeChildDeviceNodeCheckedCount(topic);
                if (serialNumberList.length > level) {
                    serialNumberList = serialNumberList.splice(0, level + 1);
                    serialNumberList[serialNumberList.length - 1]++;
                } else if (serialNumberList.length == level) {
                    if (isEmpty(serialNumberList[level])) {
                        serialNumberList[level] = 1;
                    } else {
                        serialNumberList[level]++;
                    }
                } else {
                    serialNumberList.push(1);
                }
                const serialNumber = serialNumberList.join(".");
                topic.treeLevel = level;
                topic.serialNumber = serialNumber;
                topic.childDeviceNodeCount = childDeviceNodeCount;
                topic.childDeviceNodeCheckedCount = childDeviceNodeCheckedCount;
            }
        });
        const topicTreeData: TopicType[] = deepCloneV2(_tree);
        return topicTreeData;
    }, [topicList]);

    const pureTextTopicTreeData = useMemo(() => {
        let _tree = generateTreeData(addTreePropertyForList(topicList));
        let serialNumberList = [];
        dfsRecursive(_tree, (topic: TopicType, level: number) => {
            if (topic.topicType == "text") {
                const childDeviceNodeCount = getNodeChildDeviceNodeCount(topic);
                const childDeviceNodeCheckedCount =
                    getNodeChildDeviceNodeCheckedCount(topic);
                if (serialNumberList.length > level) {
                    serialNumberList = serialNumberList.splice(0, level + 1);
                    serialNumberList[serialNumberList.length - 1]++;
                } else if (serialNumberList.length == level) {
                    if (isEmpty(serialNumberList[level])) {
                        serialNumberList[level] = 1;
                    } else {
                        serialNumberList[level]++;
                    }
                } else {
                    serialNumberList.push(1);
                }
                const serialNumber = serialNumberList.join(".");
                topic.treeLevel = level;
                topic.serialNumber = serialNumber;
                topic.childDeviceNodeCount = childDeviceNodeCount;
                topic.childDeviceNodeCheckedCount = childDeviceNodeCheckedCount;
            }
        });
        _tree = filterTree(_tree, (node) => node.topicType == "text");
        const _pureTextTopicTreeData: TopicType[] = deepCloneV2(_tree);
        return _pureTextTopicTreeData;
    }, [topicList]);

    const filteredForPureTextTopicTree = useMemo(() => {
        let _tree = generateTreeData(addTreePropertyForList(topicList));
        let serialNumberList = [];
        dfsRecursive(_tree, (topic: TopicType, level: number) => {
            if (topic.topicType == "text") {
                if (serialNumberList.length > level) {
                    serialNumberList = serialNumberList.splice(0, level + 1);
                    serialNumberList[serialNumberList.length - 1]++;
                } else if (serialNumberList.length == level) {
                    if (isEmpty(serialNumberList[level])) {
                        serialNumberList[level] = 1;
                    } else {
                        serialNumberList[level]++;
                    }
                } else {
                    serialNumberList.push(1);
                }
                const serialNumber = serialNumberList.join(".");
                topic.treeLevel = level;
                topic.serialNumber = serialNumber;
            }
        });
        _tree = filterTree(_tree, (node) =>
            node.topicName.includes(pureTextTopicTreeDataSearchValue)
        );
        const _pureTextTopicTreeData: TopicType[] = deepCloneV2(_tree);
        return _pureTextTopicTreeData;
    }, [pureTextTopicTreeDataSearchValue, topicList]);

    const filteredForRealTextTopicTree = useMemo(() => {
        let _tree = generateTreeData(addTreePropertyForList(topicList));
        let serialNumberList = [];
        dfsRecursive(_tree, (topic: TopicType, level: number) => {
            if (topic.topicType == "text") {
                if (serialNumberList.length > level) {
                    serialNumberList = serialNumberList.splice(0, level + 1);
                    serialNumberList[serialNumberList.length - 1]++;
                } else if (serialNumberList.length == level) {
                    if (isEmpty(serialNumberList[level])) {
                        serialNumberList[level] = 1;
                    } else {
                        serialNumberList[level]++;
                    }
                } else {
                    serialNumberList.push(1);
                }
                const serialNumber = serialNumberList.join(".");
                topic.treeLevel = level;
                topic.serialNumber = serialNumber;
            }
        });
        _tree = filterTree(
            _tree,
            (node) =>
                node.topicType == "text" &&
                pureTextTreeDataCheckedKeyList.includes(node.id)
        );
        _tree = filterTree(_tree, (node) =>
            node.topicName.includes(realTextTopicTreeDataSearchValue)
        );
        const _pureTextTopicTreeData: TopicType[] = deepCloneV2(_tree);
        return _pureTextTopicTreeData;
    }, [realTextTopicTreeDataSearchValue, topicList]);

    const onNodeContextMenu = (
        e: React.MouseEvent<HTMLDivElement, MouseEvent>,
        node: TopicType
    ) => {
        if (!isEmpty(pureTextTopicTreeDataSearchValue)) {
            toastShort("warning", "请退出搜索模式后重试");
            return false;
        }
        e.preventDefault();
        e.stopPropagation();
        setPureTextTopicTreeHighLightNode(node);
        setPureTextTopicTreeSelectedNode(node);
        let originX = e.clientX;
        let originY = e.clientY;
        originY = originY - 42;
        if (originY + 268 > windowFullHeight) {
            originY = windowFullHeight - 350;
        }
        e.clientX = originX;
        e.clientY = originY;
        contextMenuRef.current.showContextMenu(e);
    };

    const onDoubleClickTextTopic = (
        e: React.MouseEvent<HTMLDivElement, MouseEvent>,
        node: TopicType
    ) => {
        e.preventDefault();
        e.stopPropagation();
        setPureTextTopicTreeHighLightNode(node);
        setPureTextTopicTreeSelectedNode(node);
        onPickerTreeNodeActionType("ReName", node);
    };

    const adaptNodeSerialNumber = (node: TopicType) => {
        if (node.topicType == "device") {
            return null;
        }
        return (
            <div className="topic-tree-node-extra">{node.serialNumber}&nbsp;</div>
        );
    };

    const formatSearchTextForAllTopicTree = (originStr: string) => {
        try {
            if (isEmpty(pureTextTopicTreeDataSearchValue)) {
                return originStr;
            }
            let reg = new RegExp(pureTextTopicTreeDataSearchValue);
            let str = originStr.split(reg);
            let txt = [];
            if (str.length === 0 || str.length === 1) {
                return originStr;
            }
            if (str.length > 0) {
                txt.push(<span key={"0-0"}>{str[0]}</span>);
            }
            txt.push(
                <span key={"0-1"} style={{ color: "#ff0000" }}>
                    {pureTextTopicTreeDataSearchValue}
                </span>
            );
            if (str.length > 1) {
                txt.push(<span key={"0-2"}>{str[1]}</span>);
            }
            if (str.length >= 3) {
                for (let i = 2; i < str.length; i++) {
                    txt.push(
                        <span key={"0-3"} style={{ color: "#ff0000" }}>
                            {pureTextTopicTreeDataSearchValue}
                        </span>
                    );
                    txt.push(<span key={"0-4"}>{str[i]}</span>);
                }
            }
            return txt;
        } catch (e) {
            return originStr;
        }
    };

    const formatSearchTextForRealTopicTree = (originStr: string) => {
        try {
            if (isEmpty(realTextTopicTreeDataSearchValue)) {
                return originStr;
            }
            let reg = new RegExp(realTextTopicTreeDataSearchValue);
            let str = originStr.split(reg);
            let txt = [];
            if (str.length === 0 || str.length === 1) {
                return originStr;
            }
            if (str.length > 0) {
                txt.push(<span key={"0-0"}>{str[0]}</span>);
            }
            txt.push(
                <span key={"0-1"} style={{ color: "#ff0000" }}>
                    {realTextTopicTreeDataSearchValue}
                </span>
            );
            if (str.length > 1) {
                txt.push(<span key={"0-2"}>{str[1]}</span>);
            }
            if (str.length >= 3) {
                for (let i = 2; i < str.length; i++) {
                    txt.push(
                        <span key={"0-3"} style={{ color: "#ff0000" }}>
                            {realTextTopicTreeDataSearchValue}
                        </span>
                    );
                    txt.push(<span key={"0-4"}>{str[i]}</span>);
                }
            }
            return txt;
        } catch (e) {
            return originStr;
        }
    };

    const renderPureTextTopicTreeNode = (node: TopicType) => {
        const isDragging = node.key === draggingNodeKey;
        const className = isDragging ? "draggingNode" : "";
        return (
            <div
                className={makeClassNameList(["device-manage-tree-node", className])}
                //@ts-ignore
                topic-type={node.topicType}
                key={node.id}
                onContextMenu={(e) => onNodeContextMenu(e, node)}
                onDoubleClick={(e) => onDoubleClickTextTopic(e, node)}
                style={
                    pureTextTopicTreeHighLightNode &&
                        pureTextTopicTreeHighLightNode.id == node.id
                        ? { backgroundColor: "#f2f2f2" }
                        : null
                }
            >
                <div
                    className="flex-row device-manage-tree-node-content"
                    style={
                        pureTextTopicTreeHighLightNode &&
                            pureTextTopicTreeHighLightNode.id == node.id
                            ? { borderBottom: "1px solid #7f7f7f" }
                            : null
                    }
                >
                    {adaptNodeSerialNumber(node)}
                    <div
                        className="single-line-text"
                        style={{
                            maxWidth: 280,
                            fontWeight: node.topicType == "text" ? "normal" : "bold",
                        }}
                    >
                        {formatSearchTextForAllTopicTree(node.title)}
                        {/* {node.checked + ''} */}
                        {/* {node.realCheckedStatus + ''} */}
                    </div>
                    {/* {node.topicType == "text" &&
                        node.childDeviceNodeCount &&
                        node.childDeviceNodeCount != node.directDeviceChildNodeCount ? (
                        <Tooltip title={"本节包含项目总数量"}>
                            <div className="flex-row device-manage-tree-node-total-count">
                                {node.childDeviceNodeCount}
                            </div>
                        </Tooltip>
                    ) : null}
                    {node.topicType == "text" && node.childDeviceNodeCheckedCount ? (
                        <Tooltip title={"本节选择项目总数量"}>
                            <div className="flex-row device-manage-tree-node-count">
                                {node.childDeviceNodeCheckedCount}
                            </div>
                        </Tooltip>
                    ) : null} */}
                </div>
            </div>
        );
    };

    const renderRealTextTopicTreeNode = (node: TopicType) => {
        const isDragging = node.key === draggingNodeKey;
        const className = isDragging ? "draggingNode" : "";
        return (
            <div
                className={makeClassNameList(["device-manage-tree-node", className])}
                //@ts-ignore
                topic-type={node.topicType}
                key={node.id}
                // onContextMenu={(e) => onNodeContextMenu(e, node)}
                // onDoubleClick={(e) => onDoubleClickTextTopic(e, node)}
                style={
                    realTextTopicTreeHighLightNode &&
                        realTextTopicTreeHighLightNode.id == node.id
                        ? { backgroundColor: "#f2f2f2" }
                        : null
                }
            >
                <div
                    className="flex-row device-manage-tree-node-content"
                    style={
                        realTextTopicTreeHighLightNode &&
                            realTextTopicTreeHighLightNode.id == node.id
                            ? { borderBottom: "1px solid #7f7f7f" }
                            : null
                    }
                >
                    {adaptNodeSerialNumber(node)}
                    <div
                        className="single-line-text"
                        style={{
                            maxWidth: 280,
                            fontWeight: node.topicType == "text" ? "normal" : "bold",
                        }}
                    >
                        {formatSearchTextForRealTopicTree(node.title)}
                    </div>
                    {node.topicType == "text" &&
                        node.childDeviceNodeCount &&
                        node.childDeviceNodeCount != node.directDeviceChildNodeCount ? (
                        <Tooltip title={"本节包含项目总数量"}>
                            <div className="flex-row device-manage-tree-node-total-count">
                                {node.childDeviceNodeCount}
                            </div>
                        </Tooltip>
                    ) : null}
                    {node.topicType == "text" && node.childDeviceNodeCheckedCount ? (
                        <Tooltip title={"本节选择项目总数量"}>
                            <div className="flex-row device-manage-tree-node-count">
                                {node.childDeviceNodeCheckedCount}
                            </div>
                        </Tooltip>
                    ) : null}
                </div>
            </div>
        );
    };

    const onSelectPureTextTopicNode = (ids: string[]) => {
        const findTopicNode = topicList.find((ele) => {
            return ele.id == ids[0];
        });
        setPureTextTopicTreeSelectedNode(findTopicNode);
        setPureTextTopicTreeHighLightNode(findTopicNode);
    };

    const onSelectRealTextTopicNode = (ids: string[]) => {
        const findTopicNode = topicList.find((ele) => {
            return ele.id == ids[0];
        });
        setRealTextTopicTreeSelectedNode(findTopicNode);
        setRealTextTopicTreeHighLightNode(findTopicNode);
    };

    const onPureTextTreeDataCheckedChange = (checkedKeys: string[]) => {
        // console.log("onPureTextTreeDataCheckedChange--->", checkedKeys);
        // setPureTextTreeDataCheckedKeyList(checkedKeys);
        let _tempTopicList = topicList;
        if (!isEmpty(pureTextTopicTreeDataSearchValue)) {
            const filteredTopicList: TopicType[] = tree2List([
                ...filteredForPureTextTopicTree,
            ]);
            const tempTopicTreeSelectNodeIdList = pureTextTreeDataCheckedKeyList;
            const tempDiffTopicTreeSelectNodeIdList = [];
            tempTopicTreeSelectNodeIdList.forEach((id) => {
                const find = filteredTopicList.find((node) => {
                    return node.id == id;
                });
                if (!find) {
                    tempDiffTopicTreeSelectNodeIdList.push(id);
                }
            });
            const mergedTopicTreeSelectNodeIdList =
                tempDiffTopicTreeSelectNodeIdList.concat(checkedKeys);
            let _tempTopicList = topicList;
            _tempTopicList.forEach((topic) => {
                if (mergedTopicTreeSelectNodeIdList.includes(topic.id)) {
                    topic.checked = true;
                } else if (topic.topicType == 'text') {
                    topic.checked = false;
                    topic.children.forEach(subNode => {
                        if (subNode.topicType == 'device') {
                            console.log("取消项目节点勾选")
                            subNode.checked = false;
                        }
                    })
                }
            });
            setPureTextTreeDataCheckedKeyList(mergedTopicTreeSelectNodeIdList);
        } else {
            setPureTextTreeDataCheckedKeyList(checkedKeys);
            _tempTopicList.forEach((topic) => {
                if (checkedKeys.includes(topic.id)) {
                    topic.checked = true;
                } else if (topic.topicType == 'text') {
                    topic.checked = false;
                    topic.children.forEach(subNode => {
                        if (subNode.topicType == 'device') {
                            console.log("取消项目节点勾选")
                            subNode.checked = false;
                        }
                    })
                }
            });
        }
        updateTopicList(deepCloneV2(_tempTopicList));
    };

    const scrollTo = useCallback(
        throttle((target) => {
            const { bottom: currentBottom, top: currentTop } =
                target.getBoundingClientRect();
            const { bottom: boxBottom, top: boxTop } = document
                .getElementsByClassName("ant-tree-list-holder")[1]
                .getBoundingClientRect();
            if (currentTop > boxBottom - 48) {
                document.getElementsByClassName("ant-tree-list-holder")[1].scrollTop =
                    document.getElementsByClassName("ant-tree-list-holder")[1].scrollTop +
                    32;
            }
            if (boxTop + 48 > currentBottom) {
                document.getElementsByClassName("ant-tree-list-holder")[1].scrollTop =
                    document.getElementsByClassName("ant-tree-list-holder")[1].scrollTop -
                    32;
            }
        }, 100),
        [pureTextTopicTreeRef]
    );

    const onDragOver = (info: any) => {
        if (info.event.target) {
            scrollTo(info.event.target);
        }
    };

    const onDragStart = (info) => {
        setDraggingNodeKey(info.node.key);
    };

    const onDragEnd = (e) => {
        setDraggingNodeKey(null);
    };

    const findTreeNode = (
        treeData: TopicType[],
        targetNodeId: string
    ): TopicType => {
        let findNode = null;
        treeData.forEach((node) => {
            if (node.id == targetNodeId) {
                findNode = node;
            } else if (node.children && node.children.length && !findNode) {
                let _findNode = findTreeNode(node.children, targetNodeId);
                if (_findNode) {
                    findNode = _findNode;
                }
            }
        });
        return findNode;
    };

    const findNode = (key, data) => {
        let result;
        const find = (key, data) => {
            data.forEach((item) => {
                if (item.key === key) {
                    result = item;
                } else if (item.children) {
                    find(key, item.children);
                }
            });
        };
        find(key, data);
        return result;
    };

    const deleteNode = (key, data) => {
        data.forEach((item, index, arr) => {
            if (item.key === key) {
                arr.splice(index, 1);
            } else if (item.children) {
                deleteNode(key, item.children);
            }
        });
    };

    const updateNodePid = (node: TopicType, pid: string): TopicType => {
        node.pid = pid;
        if (node.children) {
            node.children.forEach((child) => updateNodePid(child, node.key));
        }
        return node;
    };

    // 获取兄弟节点和父节点的 key
    const getSiblingsAndParent = (key, data, parentKey = null) => {
        for (const item of data) {
            if (item.key === key) {
                return { siblings: data, parentKey };
            }
            if (item.children) {
                const result = getSiblingsAndParent(key, item.children, item.key);
                if (result) return result;
            }
        }
        return null;
    };

    function reorderParentArrayBasedOnSubset(parent, subset) {
        const parentMap = new Map(parent.map((e) => [e.id, e]));
        // 更新父集中的元素属性
        subset.forEach((subElement) => {
            if (parentMap.has(subElement.id)) {
                // 直接在映射中更新元素属性
                Object.assign(parentMap.get(subElement.id), subElement);
            }
        });

        // 创建一个排序后的父集数组
        const sortedAndUpdatedParent = parent
            .filter((e) => parentMap.has(e.id)) // 保证只包括现在还存在的元素
            .sort((a, b) => {
                // 使用子集的顺序来排序父集中的元素
                const indexA = subset.findIndex((e) => e.id === a.id);
                const indexB = subset.findIndex((e) => e.id === b.id);
                return indexA - indexB;
            });

        // 返回更新和排序后的父集
        return sortedAndUpdatedParent;
    }

    const onTopicNodeDrop = (info) => {
        setDraggingNodeKey("");
        if (!isEmpty(pureTextTopicTreeDataSearchValue)) {
            toastShort("error", "搜索模式下不可使用拖拽功能");
            return;
        }
        const treeData = deepCloneV2(pureTextTopicTreeData);
        const dropKey = info.node.key;
        const dragKey = info.dragNode.key;
        const dropPos = info.node.pos.split("-");
        const dropPosition =
            info.dropPosition - Number(dropPos[dropPos.length - 1]);
        const targetNode = info.node;
        const dropNode = findNode(dropKey, treeData);
        const dragNode = findNode(dragKey, treeData);
        let newDragNode = dragNode;
        if (dropNode.topicType === "device" && !info.dropToGap) {
            toastShort("error", "当前节点不可拖拽在所选位置");
            return;
        }
        deleteNode(dragKey, treeData);
        if (info.dropToGap) {
            const siblingsAndParent = getSiblingsAndParent(dropKey, treeData);
            if (!siblingsAndParent) return; // 确保找到了兄弟节点和父节点

            const siblings = siblingsAndParent.siblings;
            const parentKey = siblingsAndParent.parentKey;
            const index = siblings.findIndex((item) => item.key === dropKey);
            if (dropPosition < 0) {
                siblings.splice(Math.max(0, index), 0, newDragNode); // 确保即使index为-1，也能正确处理
            } else {
                siblings.splice(index + 1, 0, newDragNode);
            }
            newDragNode = updateNodePid(newDragNode, parentKey);
        } else {
            if (dragNode && dragNode.pid == targetNode.id) {
                dfsRecursive(treeData, (node: TopicType) => {
                    if (node.id == targetNode.id) {
                        let findIndex = node.children.findIndex(
                            (topic) => topic.id == dragNode.id
                        );
                        let needToMoveDownNodeIndexList = [];
                        node.children.forEach((ele, index) => {
                            if (index <= findIndex) {
                                needToMoveDownNodeIndexList.push(index);
                            }
                        });
                        for (let i = needToMoveDownNodeIndexList.length - 1; i > 0; i--) {
                            const currentNodeIndex = needToMoveDownNodeIndexList[i];
                            const currentNodeBeforeIndex = needToMoveDownNodeIndexList[i - 1];
                            node.children = swapListElements(
                                node.children,
                                currentNodeBeforeIndex,
                                currentNodeIndex
                            );
                        }
                    }
                });
            } else {
                const dropNode = findNode(dropKey, treeData);
                if (dropNode.topicType === "device") {
                    return;
                }
                dropNode.children = dropNode.children || [];
                dropNode.children.unshift(dragNode);
                newDragNode = updateNodePid(dragNode, dropNode.id);
            }
        }
        //更新到数据
        if (isEmpty(newDragNode.pid)) {
            newDragNode.pid = "0";
        }
        const currentTreeDataTopicList: TopicType[] = [...tree2List(treeData)];
        currentTreeDataTopicList.forEach((ele, index) => {
            ele.index = index;
            if (newDragNode && ele.id == newDragNode.id) {
                ele = deepCloneV2(newDragNode);
            }
        });
        let newTopicList = reorderParentArrayBasedOnSubset(
            topicList,
            currentTreeDataTopicList
        );
        updateTopicList(deepCloneV2(newTopicList));
    };

    const filterFn = (data, filterText) => {
        if (!filterText) {
            return true;
        }
        return new RegExp(filterText, "i").test(data.title);
    };

    const onPureTextTopicTreeDataSearchValueChange = (
        e: ChangeEvent<HTMLInputElement>
    ) => {
        const newSearchValue = getChangeEventValue(e);
        setPureTextTopicTreeDataSearchValue(newSearchValue);
        if (!isEmpty(newSearchValue)) {
            let tempFilteredTopicTree = arrayTreeFilter(
                deepCloneV2(pureTextTopicTreeData),
                filterFn,
                newSearchValue
            );
            let tempFilteredTopicTreeExpandedKeys = expandedKeysFun(
                tempFilteredTopicTree
            );
            setFilteredForPureTopicTreeData(tempFilteredTopicTree);
            setFilteredForPureTopicTreeExpandedKeys(
                tempFilteredTopicTreeExpandedKeys
            );
        }
    };

    const onPureTextTopicTreeExpanded = (keys: string[]) => {
        setPureTextTopicTreeExpandedKeys(deepCloneV2(keys));
    };

    const expandAllNode = () => {
        let allKeys = [];
        dfsRecursive(pureTextTopicTreeData, (node: TopicType) => {
            allKeys.push(node.id);
        });
        setPureTextTopicTreeExpandedKeys(allKeys);
    };

    const unExpandAllNode = () => {
        setPureTextTopicTreeExpandedKeys([]);
    };

    const expandRealTopicTreeAllNode = () => {
        let allKeys = [];
        dfsRecursive(realTextTopicTreeData, (node: TopicType) => {
            allKeys.push(node.id);
        });
        setRealTextTopicTreeExpandedKeys(allKeys);
    };

    const unExpandRealTopicTreeAllNode = () => {
        setRealTextTopicTreeExpandedKeys([]);
    };

    const sortDeviceNodeList = (topicList: TopicType[], sortType: DeviceSortType): TopicType[] => {
        return topicList.sort((a, b) => {
            if (deviceListSortType == "default_up") {
                const parentOrder = a.parentTextTopicTitle.localeCompare(b.parentTextTopicTitle, 'zh-Hans-CN', { sensitivity: 'accent' });
                if (parentOrder === 0) {
                    return a.topicName.localeCompare(b.topicName, 'zh-Hans-CN', { sensitivity: 'accent' });
                }
                return parentOrder;
                // return a.topicName.localeCompare(b.topicName, 'zh-Hans-CN', { sensitivity: 'accent' });
            } else if (deviceListSortType == "default_down") {
                const parentOrder = b.parentTextTopicTitle.localeCompare(a.parentTextTopicTitle, 'zh-Hans-CN', { sensitivity: 'accent' });
                if (parentOrder === 0) {
                    return b.topicName.localeCompare(a.topicName, 'zh-Hans-CN', { sensitivity: 'accent' });
                }
                return parentOrder;
                // return b.topicName.localeCompare(a.topicName, 'zh-Hans-CN', { sensitivity: 'accent' });
            } else if (deviceListSortType == "checked") {
                if (a.checked && !b.checked) {
                    return -1;
                }
                if (b.checked && !a.checked) {
                    return 1;
                }
            }
            return 0;
        });
    }

    const deviceNodeList = useMemo(() => {
        let tempDeviceNodeList: TopicType[] = [];
        if (currentDeviceType == "all") {
            topicList.forEach((topic) => {
                if (topic.topicType == "device") {
                    let findTextNode = topicList.find(
                        (textTopic) => textTopic.id == topic.pid
                    );
                    if (findTextNode) {
                        topic.parentTextTopicTitle = findTextNode.topicName;
                    }
                    tempDeviceNodeList.push(topic);
                }
            });
            return sortDeviceNodeList(tempDeviceNodeList
                .filter(
                    (node) =>
                        node.title.includes(deviceTopicSearchValue) ||
                        (node.parentTextTopicTitle &&
                            node.parentTextTopicTitle.includes(deviceTopicSearchValue))
                ), deviceListSortType)

        }
        if (realTextTopicTreeSelectedNode) {
            dfsRecursive(topicTree, (node: TopicType, level: number) => {
                if (node.id == realTextTopicTreeSelectedNode.id) {
                    dfsRecursive(node.children, (subNode: TopicType) => {
                        if (subNode.topicType == "device") {
                            let findTextNode = topicList.find(
                                (textTopic) => textTopic.id == subNode.pid
                            );
                            if (findTextNode) {
                                subNode.parentTextTopicTitle = findTextNode.topicName;
                            }
                            tempDeviceNodeList.push(subNode);
                        }
                    });
                }
            });
        }
        const _deviceNodeList = sortDeviceNodeList(tempDeviceNodeList
            .filter(
                (node) =>
                    node.title.includes(deviceTopicSearchValue) ||
                    (node.parentTextTopicTitle &&
                        node.parentTextTopicTitle.includes(deviceTopicSearchValue))
            ), deviceListSortType)
        console.log("最新的_deviceNodeList--->", _deviceNodeList);
        return _deviceNodeList;
    }, [
        topicList,
        realTextTopicTreeSelectedNode,
        deviceTopicSearchValue,
        deviceListSortType,
        currentDeviceType,
    ]);

    const onDeviceTopicSearchValueChange = (e: ChangeEvent<HTMLInputElement>) => {
        setDeviceTopicSearchValue(getChangeEventValue(e));
    };

    const checkDeviceNodeIsChecked = (node: TopicType) => {
        return node.checked;
    };

    const checkDeviceNodeIsDisable = (node: TopicType) => {
        // return false;
        if (
            realTextTopicTreeSelectedNode &&
            node.pid !== realTextTopicTreeSelectedNode.id &&
            node.checked
        ) {
            return true;
        } else {
            return false;
        }
    };

    const onCheckedChange = (e: CheckboxChangeEvent, node: TopicType) => {
        const checked = getCheckBoxChangeEventValue(e);
        let tempTopicList = topicList;
        tempTopicList.forEach((deviceNode) => {
            if (deviceNode.id == node.id) {
                deviceNode.checked = checked;
                deviceNode.pid = realTextTopicTreeSelectedNode.id;
            }
        });
        e.stopPropagation();
        e.preventDefault();
        updateTopicList(deepCloneV2(tempTopicList));
    };

    const formatDeviceTopicSearchText = (originStr: string) => {
        try {
            if (isEmpty(deviceTopicSearchValue)) {
                return originStr;
            }
            let reg = new RegExp(deviceTopicSearchValue);
            let str = originStr.split(reg);
            let txt = [];
            if (str.length === 0 || str.length === 1) {
                return originStr;
            }
            if (str.length > 0) {
                txt.push(<span key={"0-0"}>{str[0]}</span>);
            }
            txt.push(
                <span key={"0-1"} style={{ color: "#ff0000" }}>
                    {deviceTopicSearchValue}
                </span>
            );
            if (str.length > 1) {
                txt.push(<span key={"0-2"}>{str[1]}</span>);
            }
            if (str.length >= 3) {
                for (let i = 2; i < str.length; i++) {
                    txt.push(
                        <span key={"0-3"} style={{ color: "#ff0000" }}>
                            {deviceTopicSearchValue}
                        </span>
                    );
                    txt.push(<span key={"0-4"}>{str[i]}</span>);
                }
            }
            return txt;
        } catch (e) {
            return originStr;
        }
    };

    const onDeviceListSortTypeChange = (value: DeviceSortType) => {
        setDeviceListSortType(value);
    };

    function findPathInForest(forest, targetId) {
        // 遍历每一个根节点
        for (let root of forest) {
            // 调用递归函数搜索路径
            const path = findPath(root, targetId);
            // 如果找到路径（非空数组），返回这个路径
            if (path.length) {
                return path;
            }
        }
        // 如果所有根节点都没有找到路径，返回空数组
        return [];
    }

    function findPath(root, targetId) {
        if (root.id === targetId) {
            return [root.id];
        }
        if (root.children) {
            for (let child of root.children) {
                const path = findPath(child, targetId);
                if (path.length) {
                    return [root.id, ...path];
                }
            }
        }
        return [];
    }

    const clickDeviceNode = (node: TopicType) => {
        const parentTextTopic = topicList.find((ele) => ele.id == node.pid);
        if (parentTextTopic) {
            const pathIdList: string[] = findPathInForest(
                realTextTopicTreeData,
                node.pid
            );
            let _realTextTopicTreeExpandedKeys = [...realTextTopicTreeExpandedKeys];
            pathIdList.forEach((id) => {
                if (!_realTextTopicTreeExpandedKeys.includes(id)) {
                    _realTextTopicTreeExpandedKeys.push(id);
                }
            });
            setRealTextTopicTreeHighLightNode(parentTextTopic);
            setRealTextTopicTreeExpandedKeys([..._realTextTopicTreeExpandedKeys]);
            realTextTopicTreeRef.current.scrollTo({ key: node.pid });
            setTimeout(() => {
                realTextTopicTreeRef.current.scrollTo({ key: node.pid });
            }, 50);
        }
    };

    /************ 规划大纲的操作树相关逻辑 start ************/

    const addTopicModalRef = useRef<any>(null);

    const renameTopicModalRef = useRef<any>(null);

    const [currentTreeNodeActionType, setCurrentTreeNodeActionType] =
        useState<TopicNodeActionType>(null);

    const onContextMenuClose = () => {
        setPureTextTopicTreeHighLightNode(null);
    };

    const moveNode = (
        nodeList: TopicType[],
        targetId: string,
        direction: "up" | "down" | "top" | "bottom"
    ): TopicType[] => {
        let findIndex = -1;
        if (nodeList.length == 0 || nodeList.length == 1) {
            return nodeList;
        }
        for (let i = 0; i < nodeList.length; i++) {
            if (nodeList[i].id == targetId) {
                findIndex = i;
                break;
            }
        }
        if (findIndex > -1) {
            const targetNodePid = nodeList[findIndex].pid;
            switch (direction) {
                case "top":
                    let needToMoveDownNodeIndexList: number[] = [];
                    for (let i = 0; i < nodeList.length; i++) {
                        if (nodeList[i].pid == targetNodePid) {
                            if (i <= findIndex) {
                                needToMoveDownNodeIndexList.push(i);
                            }
                        }
                    }
                    if (needToMoveDownNodeIndexList[0] == findIndex) {
                        toastShort("warning", "该节点已置顶，请勿重复操作");
                    } else {
                        toastShort("success", commonSuccessMsg);
                        let _nodeList = nodeList;
                        for (let i = needToMoveDownNodeIndexList.length - 1; i > 0; i--) {
                            const currentNodeIndex = needToMoveDownNodeIndexList[i];
                            const currentNodeBeforeIndex = needToMoveDownNodeIndexList[i - 1];
                            _nodeList = swapListElements(
                                _nodeList,
                                currentNodeBeforeIndex,
                                currentNodeIndex
                            );
                        }
                        return _nodeList;
                    }
                    break;
                case "bottom":
                    let needToMoveUpNodeIndexList: number[] = [];
                    for (let i = 0; i < nodeList.length; i++) {
                        if (nodeList[i].pid == targetNodePid) {
                            if (i >= findIndex) {
                                needToMoveUpNodeIndexList.push(i);
                            }
                        }
                    }
                    if (
                        needToMoveUpNodeIndexList[needToMoveUpNodeIndexList.length - 1] ==
                        findIndex
                    ) {
                        toastShort("warning", "该节点已置底，请勿重复操作");
                    } else {
                        toastShort("success", commonSuccessMsg);
                        let _nodeList = nodeList;
                        for (let i = 0; i < needToMoveUpNodeIndexList.length; i++) {
                            const currentNodeIndex = needToMoveUpNodeIndexList[i];
                            const currentNodeBeforeIndex = needToMoveUpNodeIndexList[i - 1];
                            _nodeList = swapListElements(
                                _nodeList,
                                currentNodeBeforeIndex,
                                currentNodeIndex
                            );
                        }
                        return _nodeList;
                    }
                    break;
                case "up":
                    if (
                        nodeList[findIndex - 1] &&
                        nodeList[findIndex - 1].pid == targetNodePid
                    ) {
                        let currentChildrenNodeIndexList: number[] = [];
                        for (let i = 0; i < nodeList.length; i++) {
                            if (nodeList[i].pid == targetNodePid) {
                                if (i <= findIndex) {
                                    currentChildrenNodeIndexList.push(i);
                                }
                            }
                        }
                        let _nodeList = nodeList;
                        _nodeList = swapListElements(
                            _nodeList,
                            currentChildrenNodeIndexList[
                            currentChildrenNodeIndexList.length - 2
                            ],
                            currentChildrenNodeIndexList[
                            currentChildrenNodeIndexList.length - 1
                            ]
                        );
                        toastShort("success", commonSuccessMsg);
                        return _nodeList;
                    } else {
                        toastShort("warning", "该节点已置顶，不可继续上移");
                    }
                    break;
                case "down":
                    if (
                        nodeList[findIndex + 1] &&
                        nodeList[findIndex + 1].pid == targetNodePid
                    ) {
                        toastShort("success", commonSuccessMsg);
                        const _nodeList = swapListElements(
                            nodeList,
                            findIndex,
                            findIndex + 1
                        );
                        return _nodeList;
                    } else {
                        toastShort("warning", "该节点已置底，不可继续下移");
                    }
                    break;
                default:
                    break;
            }
            return nodeList;
        } else {
            toastShort("error", "节点不存在，请您刷新页面重试！");
        }
    };

    const handleMoveCurrentSelectedNode = (
        moveType: "up" | "down" | "top" | "bottom"
    ) => {
        try {
            let _tempTopicList = topicList;
            _tempTopicList = moveNode(
                _tempTopicList,
                pureTextTopicTreeSelectedNode.id,
                moveType
            );
            updateTopicList(deepCloneV2(_tempTopicList));
        } catch (e) {
            toastShort("error", commonErrorMsg);
        }
    };

    const [modal, contextHolder] = Modal.useModal();

    const handleDeleteCurrentSelectedNode = () => {
        modal.confirm({
            title: "温馨提示",
            icon: <ExclamationCircleOutlined />,
            content: `确认删除此${pureTextTopicTreeSelectedNode.topicType == "device" ? "项目" : "大纲"
                }？`,
            okText: "确认",
            cancelText: "取消",
            centered: true,
            onOk: confirmToDeleteCurrentSelectedNode,
        });
    };

    const confirmToDeleteCurrentSelectedNode = () => {
        try {
            let _tempTopicList = topicList;
            for (let i = 0; i < _tempTopicList.length; i++) {
                if (_tempTopicList[i].id == pureTextTopicTreeSelectedNode.id) {
                    _tempTopicList.splice(i, 1);
                    break;
                }
            }
            updateTopicList(deepCloneV2(_tempTopicList));
            toastShort("success", commonSuccessMsg);
        } catch (e) {
            toastShort("error", commonErrorMsg);
        }
    };

    const findAllDescendants = (treeData: TopicType[], nodeId: string) => {
        const result = [];
        function findDescendants(node) {
            if (!node || !node.children) return;
            node.children.forEach((child) => {
                result.push(child.id);
                findDescendants(child);
            });
        }

        function findNodeAndDescendants(nodes) {
            for (let i = 0; i < nodes.length; i++) {
                if (nodes[i].id === nodeId) {
                    findDescendants(nodes[i]);
                    break;
                }
                if (nodes[i].children) {
                    findNodeAndDescendants(nodes[i].children);
                }
            }
        }
        findNodeAndDescendants(treeData);
        return result;
    };

    const findTreePathByTargetNodeIdList = (
        treeData: TopicType[],
        nodeId: string
    ) => {
        const map = new Map();
        // 建立每个节点与其父节点的映射
        function buildMap(node, parentId = null) {
            if (!node) return;
            map.set(node.id, parentId);
            if (node.children) {
                node.children.forEach((child) => buildMap(child, node.id));
            }
        }
        // 遍历树数据，建立映射
        treeData.forEach((node) => buildMap(node));
        // 从指定节点回溯到根节点
        const path = [];
        let currentId = nodeId;
        while (currentId !== null) {
            path.push(currentId);
            currentId = map.get(currentId);
        }
        return path.reverse(); // 反转数组，使其从根节点开始
    };

    const confirmToUnCheckedCurrentSelectedNode = () => {
        try {
            // //需要直接取消勾选的节点
            let needToUnCheckedIdList = findAllDescendants(
                topicTree,
                pureTextTopicTreeSelectedNode.id
            );
            // //需要取消勾选的节点(如果此节点是勾选的话);
            let needToUnCheckedIfNodeChecedIdList = findTreePathByTargetNodeIdList(
                topicTree,
                pureTextTopicTreeSelectedNode.id
            );
            const tempTopicTreeData = generateTreeData(topicList);
            dfsRecursive(tempTopicTreeData, (node: TopicType) => {
                if (node.id == pureTextTopicTreeSelectedNode.id) {
                    node.checked = false;
                }
                if (needToUnCheckedIdList.includes(node.id)) {
                    node.checked = false;
                }
                if (needToUnCheckedIfNodeChecedIdList.includes(node.id)) {
                    node.checked = false;
                }
            });
            updateTopicList(deepCloneV2(tree2List(tempTopicTreeData)));
            toastShort("success", commonSuccessMsg);
        } catch (e) {
            toastShort("error", commonErrorMsg);
        }
    };

    const handleUnCheckedCurrentSelectedNode = () => {
        modal.confirm({
            title: "温馨提示",
            icon: <ExclamationCircleOutlined />,
            content: "确认从本文大纲中移除此节点吗？移除后您可在大纲配置中重新勾选",
            okText: "确认",
            cancelText: "取消",
            centered: true,
            onOk: confirmToUnCheckedCurrentSelectedNode,
        });
    };

    const onPickerTreeNodeActionType = (
        actionType: TopicNodeActionType,
        _pureTextTopicTreeSelectedNode?: TopicType
    ) => {
        setCurrentTreeNodeActionType(actionType);
        switch (actionType) {
            case "AddDeviceChildNode":
                addTopicModalRef.current.openModal();
                break;
            case "AddTextChildNode":
                if (Number(pureTextTopicTreeSelectedNode.topicLevel) >= 6) {
                    return toastShort("error", "大纲节点最多不能超过6级");
                }
                addTopicModalRef.current.openModal();
                break;
            case "AddDevicePeerNode":
                addTopicModalRef.current.openModal();
                break;
            case "AddTextPeerNode":
                addTopicModalRef.current.openModal();
                break;
            case "MoveUp":
                handleMoveCurrentSelectedNode("up");
                break;
            case "MoveDown":
                handleMoveCurrentSelectedNode("down");
                break;
            case "MoveTop":
                handleMoveCurrentSelectedNode("top");
                break;
            case "MoveBottom":
                handleMoveCurrentSelectedNode("bottom");
                break;
            case "ReName":
                renameTopicModalRef.current.openModal(
                    _pureTextTopicTreeSelectedNode
                        ? _pureTextTopicTreeSelectedNode.topicName
                        : pureTextTopicTreeSelectedNode.topicName
                );
                break;
            case "Delete":
                handleDeleteCurrentSelectedNode();
                break;
            case "UnChecked":
                handleUnCheckedCurrentSelectedNode();
                break;
            default:
                break;
        }
    };

    const onChangeTopic = (newTopic: TopicType, originTopic: TopicType) => {
        try {
            let _tempTreeData = topicTree;
            let _checkedTopicIdList = pureTextTreeDataCheckedKeyList;
            if (originTopic) {
                deleteNode(originTopic.id, _tempTreeData);
            }
            newTopic.checked = true;
            newTopic.childrenDeviceTopicListLength = 0;
            _checkedTopicIdList.push(newTopic.id);
            setPureTextTreeDataCheckedKeyList([..._checkedTopicIdList]);
            let newTopicNodeList = [newTopic];
            switch (currentTreeNodeActionType) {
                case "AddDeviceChildNode":
                    console.log("AddDeviceChildNode--->")
                    insertChildNodeListToTree(
                        _tempTreeData,
                        newTopicNodeList,
                        realTextTopicTreeSelectedNode.id
                    );
                    break;
                case "AddTextChildNode":
                    insertChildNodeListToTree(
                        _tempTreeData,
                        newTopicNodeList,
                        realTextTopicTreeSelectedNode.id
                    );
                    break;
                case "AddDevicePeerNode":
                    if (realTextTopicTreeSelectedNode.pid == "0") {
                        _tempTreeData = insertTopPeerNodeListToTree(
                            _tempTreeData,
                            newTopicNodeList,
                            realTextTopicTreeSelectedNode.id
                        );
                    } else {
                        insertPeerNodeListToTree(
                            _tempTreeData,
                            newTopicNodeList,
                            realTextTopicTreeSelectedNode.id
                        );
                    }
                    break;
                case "AddTextPeerNode":
                    if (realTextTopicTreeSelectedNode.pid == "0") {
                        _tempTreeData = insertTopPeerNodeListToTree(
                            _tempTreeData,
                            newTopicNodeList,
                            realTextTopicTreeSelectedNode.id
                        );
                    } else {
                        insertPeerNodeListToTree(
                            _tempTreeData,
                            newTopicNodeList,
                            realTextTopicTreeSelectedNode.id
                        );
                    }
                    break;
                default:
                    break;
            }
            const _tempTopicList = [...tree2List(_tempTreeData)];
            updateTopicList(deepCloneV2(_tempTopicList));
            toastShort("success", commonSuccessMsg);
        } catch (e) {
            toastShort("error", commonErrorMsg);
        }
    };

    const _onReNameFinish = (newName: string) => {
        let _tempTopicList = topicList;
        _tempTopicList.forEach((topic) => {
            if (topic.id == realTextTopicTreeSelectedNode.id) {
                topic.topicName = newName;
            }
        });
        updateTopicList(deepCloneV2(_tempTopicList));
    };

    /************ 规划大纲的操作树相关逻辑 end *************/

    const resetTopicListCheckedStatus = () => {
        modal.confirm({
            title: "温馨提示",
            icon: <ExclamationCircleOutlined />,
            content: `确认恢复大纲与规划项目为系统默认推荐？`,
            okText: "确认",
            cancelText: "取消",
            centered: true,
            onOk: confirmToResetTopicListCheckedStatus,
        });
    };

    const resetTopicHistoryList = (newTopicList: TopicType[]) => {
        setTopicList(newTopicList);
        setTopicHistoryIndex(0);
        const checkedPureTextTopicIdList = getInitPureTextTopicCheckedIdList(newTopicList);
        setPureTextTreeDataCheckedKeyList(checkedPureTextTopicIdList);
        const initTopicListHistoryList = [{
            _topicList: newTopicList,
            _pureTextTreeDataCheckedKeyList: deepCloneV2(checkedPureTextTopicIdList)

        }];
        setTopicListHistoryList([...initTopicListHistoryList]);
    };

    const confirmToResetTopicListCheckedStatus = () => {
        let tempTopicList = topicList;
        // console.log("tempTopicList---->", tempTopicList)
        tempTopicList.forEach(topic => {
            if (topic.topicType == 'device') {
                topic.checked = topic.defaultChecked;
            }
        })
        setTopicList(deepCloneV2(tempTopicList))
        confirmToUpdateTopicList(deepCloneV2(tempTopicList));
    };

    const checkIsSelectedAllDeviceToicList = (): boolean => {
        let isSelectedAll = true;
        if (deviceNodeList.length == 0) {
            isSelectedAll = false;
        }
        deviceNodeList.forEach((node) => {
            if (!checkDeviceNodeIsChecked(node)) {
                isSelectedAll = false;
            }
        });
        return isSelectedAll;
    };

    const switchCheckAllStatus = () => {
        const isCheckedAll = checkIsSelectedAllDeviceToicList();
        let desc = isCheckedAll
            ? "确认将面板内规划项目全部取消勾选？"
            : "确认全部勾选面板内规划项目，并将其放置到当前选中的规划大纲内容中";
        modal.confirm({
            title: "温馨提示",
            icon: <ExclamationCircleOutlined />,
            content: desc,
            okText: "确认",
            cancelText: "取消",
            centered: true,
            onOk: confirmToSwitchCheckedAllStatus,
        });
    };

    const confirmToSwitchCheckedAllStatus = () => {
        const isCheckedAll = checkIsSelectedAllDeviceToicList();
        const checked = !isCheckedAll;
        let tempTopicList = topicList;
        deviceNodeList.forEach((node) => {
            const deviceNode = tempTopicList.find((ele) => ele.id == node.id);
            deviceNode.checked = checked;
            deviceNode.pid = realTextTopicTreeSelectedNode.id;
        });
        updateTopicList(deepCloneV2(tempTopicList));
    };

    const handleOpenAddDeviceTopicModal = () => {
        onPickerTreeNodeActionType("AddDeviceChildNode");
    };

    const confirmToUpdateTopicList = (_topicList?: TopicType[]) => {
        try {
            let tempTopicList = _topicList ? _topicList : topicList;
            tempTopicList.forEach((node) => {
                if (pureTextTreeDataCheckedKeyList.includes(node.id)) {
                    node.checked = true;
                }
            });
            let newTopicTree = generateTreeData(tempTopicList);
            dfsRecursive(newTopicTree, (node: TopicType) => {
                if (node.topicType == "text") {
                    if (pureTextTreeDataCheckedKeyList.includes(node.id)) {
                        node.checked = true;
                    } else {
                        node.checked = false;
                        if (node.children) {
                            node.children.forEach(subNode => {
                                if (subNode.topicType == 'device') {
                                    subNode.checked = false;
                                }
                            })
                        }
                    }
                    let childDeviceTopicTotalCount = 0;
                    let childDeviceTopucCheckedCount = 0;
                    if (node.children && node.children.length) {
                        node.children.forEach((subNode) => {
                            if (subNode.topicType == "device") {
                                if (subNode.checked) {
                                    childDeviceTopucCheckedCount++;
                                }
                                childDeviceTopicTotalCount++;
                            }
                        })
                    }
                    if (node.checked) {
                        if (
                            childDeviceTopicTotalCount &&
                            childDeviceTopicTotalCount !== childDeviceTopucCheckedCount
                        ) {
                            node.checked = false;
                        }
                    }
                }
            });
            const newTopicList = tree2List(newTopicTree);
            const _newTopicList = deepCloneV2(newTopicList);
            let _tempComDocInstance = comDocInstance;
            _tempComDocInstance.topicList = _newTopicList;
            handleUpdateComDocInstance(deepCloneV2(_tempComDocInstance));
            resetTopicHistoryList(_newTopicList);
            if (!_topicList) {
                emitter.emit("AutoSwitchNavType", { newNavType: "excel" });
                toastShort("success", "大纲配置已更新，已为您自动跳转至投资估算表格");
            } else {
                toastShort("success", "重置成功！")
            }
        } catch (e) {
            toastShort("error", "保存失败,请您稍后重试");
        }
    };

    const handleUpdateComDocInstance = (newComDocInstance: DocInstance) => {
        let _newComDocInstance = processDocInstanceBeforeUpdate(newComDocInstance);
        _newComDocInstance.updateComponentName = "TopicSettingPopover";
        _newComDocInstance.topicList = newComDocInstance.topicList.map((topic) => {
            delete topic.children;
            return topic;
        });
        setDelayUpdateComDocInstance({ ..._newComDocInstance });
    };

    const onRealTextTopicTreeDataSearchValueChange = (
        e: ChangeEvent<HTMLInputElement>
    ) => {
        const newSearchValue = getChangeEventValue(e);
        setRealTextTopicTreeDataSearchValue(getChangeEventValue(e));
        if (!isEmpty(newSearchValue)) {
            let tempFilteredTopicTree = arrayTreeFilter(
                deepCloneV2(realTextTopicTreeData),
                filterFn,
                newSearchValue
            );
            let tempFilteredTopicTreeExpandedKeys = expandedKeysFun(
                tempFilteredTopicTree
            );
            console.log(
                "tempFilteredTopicTreeExpandedKeys--->",
                tempFilteredTopicTreeExpandedKeys
            );
            setFilteredForRealTopicTreeData(tempFilteredTopicTree);
            setFilteredForRealTopicTreeExpandedKeys(
                tempFilteredTopicTreeExpandedKeys
            );
        }
    };

    const realTextTopicTreeData = useMemo(() => {
        let _tree = generateTreeData(addTreePropertyForList(deepCloneV2(topicList)));
        dfsRecursive(_tree, (topic: TopicType, level: number) => {
            if (topic.topicType == "text") {
                const childDeviceNodeCount = getNodeChildDeviceNodeCount(topic);
                const childDeviceNodeCheckedCount =
                    getNodeChildDeviceNodeCheckedCount(topic);
                topic.childDeviceNodeCount = childDeviceNodeCount;
                topic.childDeviceNodeCheckedCount = childDeviceNodeCheckedCount;
            }
        });
        _tree = filterTree(
            _tree,
            (node) =>
                node.topicType == "text" &&
                pureTextTreeDataCheckedKeyList.includes(node.id)
        );
        let serialNumberList = [];
        dfsRecursive(_tree, (topic: TopicType, level: number) => {
            if (topic.topicType == "text") {
                if (serialNumberList.length > level) {
                    serialNumberList = serialNumberList.splice(0, level + 1);
                    serialNumberList[serialNumberList.length - 1]++;
                } else if (serialNumberList.length == level) {
                    if (isEmpty(serialNumberList[level])) {
                        serialNumberList[level] = 1;
                    } else {
                        serialNumberList[level]++;
                    }
                } else {
                    serialNumberList.push(1);
                }
                const serialNumber = serialNumberList.join(".");
                topic.treeLevel = level;
                topic.serialNumber = serialNumber;
            }
        });
        const _pureTextTopicTreeData: TopicType[] = deepCloneV2(_tree);
        return _pureTextTopicTreeData;
    }, [topicList, pureTextTreeDataCheckedKeyList]);

    const onRealTextTopicTreeExpandedKeys = (keys: string[]) => {
        setRealTextTopicTreeExpandedKeys(keys);
    };

    const backToSelectTitle = () => {
        setCurrentStep("selectTitle");
        setRealTextTopicTreeDataSearchValue("");
        setRealTextTopicTreeSelectedNode(null);
        setRealTextTopicTreeHighLightNode(null);
    };

    const undoTopicList = () => {
        console.log("topicListHistoryList---->", topicListHistoryList)
        const newTopicListHistoryIndex = topicListHistoryIndex - 1;
        let newTopicList = topicListHistoryList[newTopicListHistoryIndex]._topicList;
        setTopicList(deepCloneV2(newTopicList));
        setTopicHistoryIndex(newTopicListHistoryIndex);
        const _checkedPureTextTopicIdList = topicListHistoryList[newTopicListHistoryIndex]._pureTextTreeDataCheckedKeyList;
        console.log(_checkedPureTextTopicIdList, _checkedPureTextTopicIdList.length)
        setPureTextTreeDataCheckedKeyList(deepCloneV2(_checkedPureTextTopicIdList));
    };

    const redoTopicList = () => {
        console.log("topicListHistoryList---->", topicListHistoryList)
        const newTopicListHistoryIndex = topicListHistoryIndex + 1;
        let newTopicList = topicListHistoryList[newTopicListHistoryIndex]._topicList;
        setTopicList([...newTopicList]);
        setTopicHistoryIndex(newTopicListHistoryIndex);
        const _checkedPureTextTopicIdList = topicListHistoryList[newTopicListHistoryIndex]._pureTextTreeDataCheckedKeyList;
        console.log(_checkedPureTextTopicIdList, _checkedPureTextTopicIdList.length)
        setPureTextTreeDataCheckedKeyList(deepCloneV2(_checkedPureTextTopicIdList));
    };

    return (
        <div style={{ width: "100%", height: "100%" }}>
            <div className="flex-row topic-manage-page-container">
                <div className="flex-col topic-manage-page-content">
                    <div className="flex-row topic-manage-page-panel-row">
                        {/*  */}
                        <div className="flex-col topic-manage-page-pannel">
                            {currentStep == "selecteDevice" ? (
                                <div className="flex-col topic-manage-page-pannel-overlay"></div>
                            ) : null}
                            <div className="flex-row topic-manage-page-pannel-title">
                                <div className="flex-row">
                                    <div className="topic-manage-page-pannel-step">1</div>
                                    <div className="topic-manage-page-pannel-title-text">
                                        规划大纲编制
                                    </div>
                                </div>
                                <div className="flex-row">
                                    {/* <Tooltip title={"上一步"}>
                                        <Button type={'text'}><UndoOutlined /></Button>
                                    </Tooltip>
                                    <Tooltip title={"下一步"}>
                                        <Button type={'text'}><RedoOutlined /></Button>
                                    </Tooltip> */}
                                    <Tooltip title={"展开所有级别大纲"}>
                                        <Button
                                            type={"text"}
                                            onClick={expandAllNode}
                                            disabled={!isEmpty(pureTextTopicTreeDataSearchValue)}
                                        >
                                            <ExpandAltOutlined
                                                style={{ transform: `rotateZ(-45deg)` }}
                                            />
                                        </Button>
                                    </Tooltip>
                                    <Tooltip title={"收起所有级别大纲"}>
                                        <Button
                                            type={"text"}
                                            onClick={unExpandAllNode}
                                            disabled={!isEmpty(pureTextTopicTreeDataSearchValue)}
                                        >
                                            <VerticalAlignMiddleOutlined />
                                        </Button>
                                    </Tooltip>
                                </div>
                            </div>
                            <div className="topic-manage-page-pannel-body">
                                <Search
                                    placeholder="搜索规划大纲"
                                    style={{ marginBottom: 10 }}
                                    value={pureTextTopicTreeDataSearchValue}
                                    onChange={onPureTextTopicTreeDataSearchValueChange}
                                    allowClear
                                    maxLength={10}
                                />
                                <Tree
                                    ref={pureTextTopicTreeRef}
                                    style={{ width: "100%", overflow: "hidden" }}
                                    showLine
                                    autoExpandParent={false}
                                    defaultExpandAll={false}
                                    switcherIcon={<DownOutlined />}
                                    checkable={true}
                                    //@ts-ignore
                                    titleRender={renderPureTextTopicTreeNode}
                                    expandedKeys={
                                        isEmpty(pureTextTopicTreeDataSearchValue)
                                            ? pureTextTopicTreeExpandedKeys
                                            : filteredForPureTopicTreeExpandedKeys
                                    }
                                    onExpand={onPureTextTopicTreeExpanded}
                                    //@ts-ignore
                                    treeData={
                                        isEmpty(pureTextTopicTreeDataSearchValue)
                                            ? pureTextTopicTreeData
                                            : filteredForPureTextTopicTree
                                    }
                                    selectedKeys={
                                        pureTextTopicTreeSelectedNode
                                            ? [pureTextTopicTreeSelectedNode.id]
                                            : []
                                    }
                                    onSelect={onSelectPureTextTopicNode}
                                    checkedKeys={pureTextTreeDataCheckedKeyList}
                                    onCheck={onPureTextTreeDataCheckedChange}
                                    height={windowFullHeight - 250}
                                    blockNode
                                    draggable={{
                                        icon: false,
                                        nodeDraggable: () =>
                                            isEmpty(pureTextTopicTreeDataSearchValue),
                                    }}
                                    onDragStart={onDragStart}
                                    onDragOver={onDragOver}
                                    onDragEnd={onDragEnd}
                                    onDrop={onTopicNodeDrop}
                                />
                            </div>
                        </div>
                        <div className="flex-col" style={{ padding: 12 }}>
                            <Button
                                type={currentStep == "selecteDevice" ? "dashed" : "primary"}
                                style={{ marginBottom: 12 }}
                                ghost={currentStep == "selecteDevice"}
                                disabled={currentStep == "selecteDevice"}
                                onClick={() => setCurrentStep("selecteDevice")}
                            >
                                进行规划内容选择
                                <RightCircleOutlined />
                            </Button>
                            <Button
                                type={currentStep == "selectTitle" ? "dashed" : "primary"}
                                ghost={currentStep == "selectTitle"}
                                disabled={currentStep == "selectTitle"}
                                onClick={backToSelectTitle}
                            >
                                <LeftCircleOutlined />
                                重新编制规划大纲
                            </Button>
                        </div>
                        <div
                            style={{ borderLeft: "1px solid #dcdcdc" }}
                            className="flex-col topic-manage-page-pannel"
                        >
                            {currentStep == "selectTitle" ? (
                                <div className="flex-col topic-manage-page-pannel-overlay"></div>
                            ) : null}
                            <div className="flex-row topic-manage-page-pannel-title">
                                <div className="flex-row">
                                    <div className="topic-manage-page-pannel-step">2</div>
                                    <div className="topic-manage-page-pannel-title-text">
                                        规划内容选择
                                    </div>
                                </div>
                                <div className="flex-row">
                                    {/* <Button type={'text'}><UndoOutlined /></Button>
                                    <Button type={'text'}><RedoOutlined /></Button> */}
                                    <Tooltip title={"展开所有级别大纲"}>
                                        <Button
                                            type={"text"}
                                            onClick={expandRealTopicTreeAllNode}
                                            disabled={!isEmpty(realTextTopicTreeDataSearchValue)}
                                        >
                                            <ExpandAltOutlined
                                                style={{ transform: `rotateZ(-45deg)` }}
                                            />
                                        </Button>
                                    </Tooltip>
                                    <Tooltip title={"收起所有级别大纲"}>
                                        <Button
                                            type={"text"}
                                            onClick={unExpandRealTopicTreeAllNode}
                                            disabled={!isEmpty(realTextTopicTreeDataSearchValue)}
                                        >
                                            <VerticalAlignMiddleOutlined />
                                        </Button>
                                    </Tooltip>
                                </div>
                            </div>
                            {realTextTopicTreeData.length ||
                                filteredForRealTextTopicTree.length ? (
                                <div className="topic-manage-page-pannel-body">
                                    <Search
                                        placeholder="搜索规划大纲"
                                        style={{ marginBottom: 10 }}
                                        value={realTextTopicTreeDataSearchValue}
                                        onChange={onRealTextTopicTreeDataSearchValueChange}
                                        allowClear
                                    />
                                    <Tree
                                        ref={realTextTopicTreeRef}
                                        style={{ width: "100%", overflow: "hidden" }}
                                        showLine
                                        autoExpandParent
                                        defaultExpandAll={false}
                                        switcherIcon={<DownOutlined />}
                                        //@ts-ignore
                                        titleRender={renderRealTextTopicTreeNode}
                                        expandedKeys={
                                            isEmpty(realTextTopicTreeDataSearchValue)
                                                ? realTextTopicTreeExpandedKeys
                                                : filteredForRealTopicTreeExpandedKeys
                                        }
                                        onExpand={onRealTextTopicTreeExpandedKeys}
                                        //@ts-ignore
                                        treeData={
                                            isEmpty(realTextTopicTreeDataSearchValue)
                                                ? realTextTopicTreeData
                                                : filteredForRealTextTopicTree
                                        }
                                        selectedKeys={
                                            realTextTopicTreeSelectedNode
                                                ? [realTextTopicTreeSelectedNode.id]
                                                : []
                                        }
                                        onSelect={onSelectRealTextTopicNode}
                                        height={windowFullHeight - 250}
                                        blockNode
                                    />
                                </div>
                            ) : (
                                <Empty description={"请至少选择一个规划大纲"} />
                            )}
                        </div>
                        <div
                            className="flex-col topic-manage-page-pannel"
                            style={{ borderRight: "none" }}
                        >
                            {currentStep == "selectTitle" ? (
                                <div className="flex-col topic-manage-page-pannel-overlay"></div>
                            ) : null}
                            <div
                                className="flex-row topic-manage-page-pannel-title"
                                style={{ justifyContent: "space-between" }}
                            >
                                <div className="flex-row topic-manage-switch-bar">
                                    {/* <div className='topic-manage-page-pannel-step'>2</div> */}
                                    <Tooltip title={"左侧选中大纲的所有规划项目"}>
                                        <div
                                            onClick={() => setCurrentDeviceType("current")}
                                            className={makeClassNameList([
                                                "flex-row topic-manage-switch-bar-item",
                                                currentDeviceType == "current" ? "active" : null,
                                            ])}
                                        >
                                            本节项目
                                        </div>
                                    </Tooltip>
                                    <Tooltip title={"规划大纲库中的所有规划项目"}>
                                        <div
                                            onClick={() => setCurrentDeviceType("all")}
                                            className={makeClassNameList([
                                                "flex-row topic-manage-switch-bar-item",
                                                currentDeviceType == "all" ? "active" : null,
                                            ])}
                                        >
                                            所有项目
                                        </div>
                                    </Tooltip>
                                    <div
                                        className="topic-manage-switch-bar-bootom-line"
                                        style={{ left: currentDeviceType == "current" ? 11 : 92 }}
                                    ></div>
                                </div>
                                <div className="flex-row">
                                    <Tooltip title={"调整面板中的规划项目排序方式"}>
                                        <Select
                                            size={"small"}
                                            style={{ marginRight: 12 }}
                                            value={deviceListSortType}
                                            onChange={onDeviceListSortTypeChange}
                                            popupMatchSelectWidth={false}
                                            options={[
                                                {
                                                    value: "checked",
                                                    label: "选中优先",
                                                },
                                                {
                                                    value: "default_up",
                                                    label: "升序",
                                                },
                                                {
                                                    value: "default_down",
                                                    label: "降序",
                                                },
                                            ]}
                                        />
                                    </Tooltip>
                                    <Tooltip title={"添加左侧选中大纲的规划项目"}>
                                        <Button
                                            type={"primary"}
                                            size={"small"}
                                            disabled={isEmpty(realTextTopicTreeSelectedNode)}
                                            onClick={handleOpenAddDeviceTopicModal}
                                        >
                                            <PlusCircleOutlined />
                                            新建项目
                                        </Button>
                                    </Tooltip>
                                </div>
                            </div>
                            {realTextTopicTreeSelectedNode &&
                                realTextTopicTreeSelectedNode.id ? (
                                <div className="flex-col topic-manage-page-pannel-body">
                                    <div
                                        className="flex-row"
                                        style={{ width: "100%", marginBottom: 10 }}
                                    >
                                        <Search
                                            placeholder="搜索规划项目"
                                            style={{ marginRight: 10 }}
                                            value={deviceTopicSearchValue}
                                            onChange={onDeviceTopicSearchValueChange}
                                            allowClear
                                            maxLength={10}
                                        />
                                        <Tooltip title={"全选/反选面板中显示的规划项目"}>
                                            <Button
                                                type={
                                                    checkIsSelectedAllDeviceToicList()
                                                        ? "primary"
                                                        : "default"
                                                }
                                                size={"small"}
                                                // style={{ marginRight: 12 }}
                                                disabled={isEmpty(realTextTopicTreeSelectedNode)}
                                                onClick={switchCheckAllStatus}
                                            >
                                                <CheckOutlined />
                                                {checkIsSelectedAllDeviceToicList() ? '取消全选' : '全选项目'}
                                            </Button>
                                        </Tooltip>
                                    </div>
                                    {deviceNodeList.length ? (
                                        <div className="topic-manage-page-pannel-body-devicelist">
                                            <Alert
                                                message="温馨提示：（1）勾选项目，被勾选的项目将会被放置到左侧选中的大纲内容中。（2）禁用勾选的项目代表，该项目正放置在其它规划大纲内容中，若要改变其所属大纲，请先取消勾选。"
                                                type="warning"
                                                showIcon
                                                closable={true}
                                                style={{ marginBottom: 10 }}
                                            />
                                            {deviceNodeList.map((node) => {
                                                return (
                                                    <div
                                                        className="flex-row device-tree-node"
                                                        key={node.id}
                                                        title={node.title}
                                                    // onClick={() => clickDeviceNode(node)}
                                                    >
                                                        <div className="flex-row device-tree-node-content">
                                                            <Checkbox
                                                                checked={checkDeviceNodeIsChecked(node)}
                                                                onChange={(e) => onCheckedChange(e, node)}
                                                                disabled={checkDeviceNodeIsDisable(node)}
                                                            />
                                                            <div
                                                                style={{
                                                                    marginLeft: 3,
                                                                    marginRight: 3,
                                                                    opacity: checkDeviceNodeIsDisable(node)
                                                                        ? 0.52
                                                                        : 1,
                                                                }}
                                                            ></div>
                                                            <div
                                                                className="single-line-text"
                                                                style={{
                                                                    width: 420,
                                                                    fontWeight:
                                                                        node.topicType == "text"
                                                                            ? "normal"
                                                                            : "bold",
                                                                    opacity: checkDeviceNodeIsDisable(node)
                                                                        ? 0.52
                                                                        : 1,
                                                                }}
                                                            >
                                                                {node.parentTextTopicTitle ? (
                                                                    <span style={{ opacity: 0.52 }}>
                                                                        [
                                                                        {formatDeviceTopicSearchText(
                                                                            node.parentTextTopicTitle
                                                                        )}
                                                                        ]{" > "}
                                                                    </span>
                                                                ) : null}
                                                                {formatDeviceTopicSearchText(node.title)}
                                                            </div>
                                                        </div>
                                                    </div>
                                                );
                                            })}
                                        </div>
                                    ) : (
                                        <div
                                            className="flex-col"
                                            style={{ height: "100%", justifyContent: "center" }}
                                        >
                                            <Empty
                                                description={`[${realTextTopicTreeSelectedNode &&
                                                    realTextTopicTreeSelectedNode.title
                                                    }]大纲下没有规划项目`}
                                            />
                                        </div>
                                    )}
                                </div>
                            ) : (
                                <div
                                    className="flex-col topic-manage-page-pannel-body"
                                    style={{ justifyContent: "center" }}
                                >
                                    <Empty
                                        description={
                                            "请先点击左侧大纲节点, 选择大纲后即可开始选择规划内容"
                                        }
                                    />
                                </div>
                            )}
                        </div>
                    </div>
                    <div className="flex-row topic-manage-page-bottom">
                        <Button
                            style={{ marginRight: 10 }}
                            onClick={undoTopicList}
                            disabled={topicListHistoryIndex <= 0}
                        >
                            <ArrowLeftOutlined />
                            撤销
                        </Button>
                        <Button
                            style={{ marginRight: 10 }}
                            onClick={redoTopicList}
                            disabled={
                                topicListHistoryList.length == topicListHistoryIndex + 1
                            }
                        >
                            恢复
                            <ArrowRightOutlined />
                        </Button>
                        <Button
                            style={{ marginRight: 12 }}
                            icon={<UndoOutlined />}
                            type={"primary"}
                            ghost
                            onClick={resetTopicListCheckedStatus}
                        >
                            重置为默认推荐
                        </Button>
                        <Button
                            type={"primary"}
                            onClick={() => confirmToUpdateTopicList()}
                            disabled={topicListHistoryList.length < 2}
                        >
                            确认完成
                        </Button>
                    </div>
                </div>
            </div>
            <TopicTreeContextMenu
                ref={contextMenuRef}
                currentScreen={"allTopic"}
                onContextMenuClose={onContextMenuClose}
                currentTopicNode={pureTextTopicTreeSelectedNode}
                onPickerActionType={onPickerTreeNodeActionType}
                allowOption={"just-text"}
            />
            <AddTopicMoal
                ref={addTopicModalRef}
                currentTopicNode={realTextTopicTreeSelectedNode}
                currentTreeNodeActionType={currentTreeNodeActionType}
                onFinish={onChangeTopic}
            />
            <ReNameTopicModal ref={renameTopicModalRef} onFinish={_onReNameFinish} />
            {contextHolder}
        </div>
    );
};

export default TopicManagePage;
